package com.atguigu.gmall.common.service;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.entity.GmallCorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Random;
import java.util.UUID;

/**
 * @author wk
 * @create 2021-09-12 19:59
 * 发送消息
 */
@Component
public class RabbitService {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    public void sendMessage(String exchange, String routingKey, Object msg) {
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        // 添加交换机信息
        gmallCorrelationData.setExchange(exchange);
        // 添加路由键
        gmallCorrelationData.setRoutingKey(routingKey);
        // 添加消息
        gmallCorrelationData.setMessage(msg);
        // 如果队列处接收消息失败 也该重新发送 可以在发送之前将gmallCorrelationData对象存到缓存中
        // 当队列处进行消息重发时 可以获取到相关信息
        String lId = exchange + routingKey;
        String kId = UUID.randomUUID().toString();
        // 设置id
        gmallCorrelationData.setId(kId);
        // 设置到缓存中
        redisTemplate.opsForHash().put(lId, kId, JSONObject.toJSON(gmallCorrelationData));
        // 发送消息
        rabbitTemplate.convertAndSend(exchange, routingKey, msg, gmallCorrelationData);
    }

    // 发送延迟消息 基于死信
    public void sendDeadLetterMessage(String exchange, String routingKey, Object msg, int delayTime) {
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        // 添加交换机信息
        gmallCorrelationData.setExchange(exchange);
        // 添加路由键
        gmallCorrelationData.setRoutingKey(routingKey);
        // 添加消息
        gmallCorrelationData.setMessage(msg);
        // 设置是否是死信队列
        gmallCorrelationData.setDeadLetterDelay(true);
        // 设置死信停留时间
        gmallCorrelationData.setDelayTime(delayTime);
        // 如果队列处接收消息失败 也该重新发送 可以在发送之前将gmallCorrelationData对象存到缓存中
        // 当队列处进行消息重发时 可以获取到相关信息
        String lId = exchange + routingKey;
        String kId = UUID.randomUUID().toString();
        // 设置id
        gmallCorrelationData.setId(kId);
        // 设置到缓存中
        redisTemplate.opsForHash().put(lId, kId, JSONObject.toJSON(gmallCorrelationData));
        // 发送消息
        rabbitTemplate.convertAndSend(exchange, routingKey, msg, (message) -> {
            // 设置死信消息的过期时间
            message.getMessageProperties().setExpiration(String.valueOf(1000 * delayTime));
            return message;
        }, gmallCorrelationData);
    }

    // 发送延迟消息 基于插件
    public void sendDelayedMessage(String exchange, String routingKey, Object msg, int delayTime) {
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        // 添加交换机信息
        gmallCorrelationData.setExchange(exchange);
        // 添加路由键
        gmallCorrelationData.setRoutingKey(routingKey);
        // 添加消息
        gmallCorrelationData.setMessage(msg);
        // 设置是否是死信队列
        gmallCorrelationData.setDelayedDelay(true);
        // 设置死信停留时间
        gmallCorrelationData.setDelayTime(delayTime);
        // 如果队列处接收消息失败 也该重新发送 可以在发送之前将gmallCorrelationData对象存到缓存中
        // 当队列处进行消息重发时 可以获取到相关信息
        String lId = exchange + routingKey;
        String kId = UUID.randomUUID().toString();
        // 设置id
        gmallCorrelationData.setId(kId);
        // 设置到缓存中
        redisTemplate.opsForHash().put(lId, kId, JSONObject.toJSON(gmallCorrelationData));
        // 发送消息
        rabbitTemplate.convertAndSend(exchange, routingKey, msg, (message) -> {
            // 设置延迟消息的延迟时间
            message.getMessageProperties().setDelay(1000 * delayTime);
            return message;
        }, gmallCorrelationData);

    }
}
